<?php

/**
 * Crud interface for Zend Db Tables
 *
 * @author    Mon Zafra <monzee at gmail>
 * @copyright (c)2009 Mon Zafra
 * @license   http://monzee.wordpress.com/license New BSD
 * @version   $Id: IndexController.php 38 2009-02-18 17:12:39Z monzee $
 * @todo      split actions into various controllers?
 */
class Crud_IndexController extends Zend_Controller_Action
{
    /**
     * @var Zend_Db_Adapter_Abstract
     */
    protected $_db;
    /**
     * @var Zend_Db_Table_Abstract
     */
    protected $_table;
    protected $_message;

    public function init()
    {
        $this->_db = $this->_helper->module('crud')->getAdapter();
        if (null === $this->_db) {
            throw new Zend_Db_Table_Exception('[CRUD] Zend_Db_Table default adapter not set!');
        }

        if ($this->_hasParam('table')) {
            $tableName = $this->_getParam('table');
            $this->_table = new Crud_Table(array(
                Zend_Db_Table_Abstract::ADAPTER => $this->_db,
                Zend_Db_Table_Abstract::NAME => $tableName,
            ));
        }
    }

    public function postDispatch()
    {
        $flash = $this->getHelper('FlashMessenger');
        /* @var $flash Zend_Controller_Action_Helper_FlashMessenger */
        $flash->setNamespace('crud');
        if ($flash->hasMessages()) {
            $this->view->messages = $flash->getMessages();
        }
    }

    public function indexAction()
    {
       if ($this->_hasParam('table')) {
           $this->_forward('list');
           return;
       }
       
       $this->view->tables = $this->_db->listTables();
    }

    public function listAction()
    {
        if (null === $table = $this->_table) {
            $this->_setParam('table', null);
            $this->_forward('index');
            return;
        }
        $tableName = $table->getTableName();

        $sel = $this->_db->select()->from($tableName, '*');
        if ($this->_hasParam('sort')) {
            $ord = $this->_hasParam('order')
                 ? strtoupper($this->_getParam('order'))
                 : 'ASC';
            $sel->order($this->_getParam('sort') . ' ' . $ord);
            $this->view->sort = $this->_getParam('sort');
        }
        $paginator = Zend_Paginator::factory($sel);
        $paginator->setCurrentPageNumber($this->_getParam('page', 1))
                  ->setItemCountPerPage($this->_getParam('perpage', 10));

        $this->view->table = $tableName;
        $this->view->headers = $table->getColumns();
        $this->view->primary = $table->getPrimaryKeys();
        $this->view->data = $paginator;
    }

    public function readAction()
    {
        if (null === $table = $this->_table) {
            $this->_setParam('table', null);
            $this->_forward('index');
            return;
        }
        $req = $this->getRequest();

        if ($req->isPost()) {
            if ($req->getPost('edit')) {
                $this->_redirect($this->_helper->url->url(array('action' => 'update')));
            } else if ($req->getPost('delete')) {
                $this->_redirect($this->_helper->url->url(array('action' => 'delete')));
            }
            return;
        }

        $params = $req->getUserParams();
        foreach ($params as &$value) {
            $value = urldecode($value);
        }
        $this->view->table = $table->getTableName();
        $this->view->data = $table->getRow($params)->toArray();
    }

    public function createAction()
    {
        if (null === $table = $this->_table) {
            $this->_setParam('table', null);
            $this->_forward('index');
            return;
        }
        $req = $this->getRequest();
        $form = new Crud_TableForm($table);

        if ($req->isPost()) {
            if ($form->isValid($req->getPost())) {
                if (!empty($form->password)) {
                    $form->password->setValue(md5($form->getValue('password')));
                }
                $new = $table->createRow();
                $values = $form->getValues();
                $this->_save($new, $values);

                $this->_helper->flashMessenger
                     ->setNamespace('crud')
                     ->addMessage('New record added.');
                $this->_redirect($this->_helper->url->url($req->getUserParams()));
                return;
            } else {
                $this->_helper->flashMessenger
                     ->setNamespace('error')
                     ->addMessage('There were some problems with your request.');
            }
        }

        if ($date = $form->getElement('created_at')) {
            $date->setValue(Zend_Date::now()->toString('YYYY-MM-dd HH:mm:ss'));
        }
        $this->view->table = $table->getTableName();
        $this->view->form = $form;
    }

    public function updateAction()
    {
        if (null === $table = $this->_table) {
            $this->_setParam('table', null);
            $this->_forward('index');
            return;
        }
        $req = $this->getRequest();
        $params = $req->getUserParams();
        foreach ($params as &$value) {
            $value = urldecode($value);
        }

        $form = new Crud_TableForm($table);
        $row = $table->getRow($params);

        if (!$req->isPost()) {
            $form->populate($row->toArray());
        } else {
            if ($form->isValid($req->getPost())) {
                if (!empty($form->password)) {
                    $val = $form->getValue('password');
                    $val = !empty($val) ? md5($val) : null;
                    $form->password->setValue($val);
                }
                $values = $form->getValues();
                $this->_save($row, $values);
                $this->_helper->flashMessenger
                     ->setNamespace('crud')
                     ->addMessage('Record updated.');

                $url = $params;
                $url['action'] = 'list';
                $url['id'] = null;
                $this->_redirect($this->_helper->url->url($url));
                return;
            }
        }

        if (($date = $form->getElement('updated_at')) && null === $date->getValue()) {
            $date->setValue(Zend_Date::now()->toString('YYYY-MM-dd HH:mm:ss'));
        }
        $this->view->table = $table->getTableName();
        $this->view->form = $form;
    }

    public function deleteAction()
    {
        if (null === $table = $this->_table) {
            $this->_setParam('table', null);
            $this->_forward('index');
            return;
        }
        $req = $this->getRequest();
        $params = $req->getUserParams();
        foreach ($params as &$value) {
            $value = urldecode($value);
        }

        $row = $table->getRow($params);
        if ($req->isPost()) {
            if ($req->getPost('yes')) {
                $row->delete();
                $this->_helper->flashMessenger
                     ->setNameSpace('crud')
                     ->addMessage('Record deleted.');
            } else {
                $this->_helper->flashMessenger
                     ->setNameSpace('crud')
                     ->addMessage('Delete cancelled.');
            }
            $url = array('module' => 'crud', 'controller' => 'index', 
                         'action' => 'list', 'table' => $params['table']);
            $this->_redirect($this->_helper->url->url($url, null, true));
            return;
        }

        $this->view->table = $table->getTableName();
        $this->view->data = $row->toArray();
        $this->view->pk = $table->getPrimaryKeys();
    }

    /**
     * save a row, catch any exception
     *
     * @param Zend_Db_Table_Row_Abstract $row
     * @param array $values
     */
    protected function _save($row, $values)
    {
        foreach ($values as $key => $val) {
            if (null == $val) {
                unset($values[$key]);
            }
        }

        try {
            $profiler = $this->_db->getProfiler()->setEnabled(true);
            $row->setFromArray($values)
                ->save();
        } catch (Zend_Db_Statement_Exception $e) {
            $query = $profiler->getLastQueryProfile();
            $this->_helper->flashMessenger
                 ->setNamespace('crud')
                 ->addMessage($e->getMessage())
                 ->addMessage('Query was: <strong>' . $query->getQuery() . '</strong>')
                 ->addMessage('Values were: <strong>' . print_r($query->getQueryParams(), true) . '</strong>');
        }
    }

}
